package com.langshixiaobai.game;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.langshixiaobai.Main;
import com.langshixiaobai.eneity.User;
import com.langshixiaobai.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.UUID;

//1. 由于Room需要被new，不是单例，如果要用Component需要设置成单例模式
//2. 也可以用过ApplicationContext应用上下文获取spring  ioc容器中的bean
public class Room {

    private User user1;
    private User user2;

    private Integer whiteUser;

    private String roomId;


    private OnlineUserMap onlineUserMap = Main.context.getBean(OnlineUserMap.class);


    private RoomManager roomManager = Main.context.getBean(RoomManager.class);

    private ObjectMapper objectMapper = new ObjectMapper();

    private UserMapper userMapper = Main.context.getBean(UserMapper.class);

    private int MAX_ROW = 15;

    private int MAX_COL = 15;

    //创建服务器端棋盘
    private int[][] chessBoard = new int[MAX_ROW][MAX_COL];

    public Room() {
        //通过uuid生成唯一房间id
        this.roomId = UUID.randomUUID().toString();
    }

    public void putChess(String reqJson) {
        try {
            GameRequest request = objectMapper.readValue(reqJson, GameRequest.class);
            // 判断当前时用户1落子还是用户2落子
            int pressId = request.getUserId() == this.user1.getUserId() ? 1 : 2;
            int col = request.getCol();
            int row = request.getRow();
            String message = request.getMessage();
            if (message.equals("putChess")) {
                if (chessBoard[row][col] != 0) {
                    System.out.println("用户：" + pressId + "落子重复");
                    return;
                }

                GameResponse response = new GameResponse();
                response.setMessage("putChess");
                response.setRow(row);
                response.setCol(col);
                //设置下棋子用户id

                response.setUserId(pressId);

                chessBoard[row][col] = pressId;
                //TODO 进行棋子判定
                int winner = checkChess(pressId, row, col);
                response.setWinner(winner);

                WebSocketSession session1 = onlineUserMap.getFromGameRoom(user1.getUserId());
                WebSocketSession session2 = onlineUserMap.getFromGameRoom(user2.getUserId());
                if (session1 == null) {
                    //如果用户1断线，则用户2赢
                    response.setWinner(user2.getUserId());

                }
                if (session2 == null) {
                    //如果用户2断线，则用户1赢
                    response.setWinner(user1.getUserId());
                }
                //给用户1，用户2返回响应消息
                if (session1 != null) {

                    session1.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
                }
                if (session2 != null) {
                    session2.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
                }
                //当用户获胜时候，移除房间信息
                if (response.getWinner() != 0) {
                    //保存到数据库中
                    int userWinner = response.getWinner() == user1.getUserId() ? user1.getUserId() : user2.getUserId();
                    int userLoser = response.getWinner() == user1.getUserId() ? user2.getUserId() : user1.getUserId();
                    // 更新数据库分数
                    userMapper.updateWinner(userWinner);

                    userMapper.updateWinner(userLoser);

                    roomManager.removeRoom(roomId, user1.getUserId(), user2.getUserId());
                }
            }
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            e.printStackTrace();
            ;
        }
    }

    public int checkChess(int pressId, int row, int col) {
        //算法思路：通过先获取下棋点的每种情况的起点
        //通过从起点进行遍历，如果后面五个都满足条件，则代表胜利
        //可能越界，通过异常捕获跳过即可
        // cel = col - 4    代表获取最左边起点 cel++ 从起点向落子点遍历
        // cel = col + 4    代表获取最右边起点 cel-- 从起点向落子店遍历

        for (int cel = col - 4; cel <= col; cel++) {
            try {
                //TODO 验证算法，目前只只实现一行
                if (chessBoard[row][cel] == pressId &&
                        chessBoard[row][cel + 1] == pressId &&
                        chessBoard[row][cel + 2] == pressId &&
                        chessBoard[row][cel + 3] == pressId &&
                        chessBoard[row][cel + 4] == pressId
                ) {
                    return pressId;
                }
            } catch (ArrayIndexOutOfBoundsException e) {
                System.out.println("正常错误");
            }
        }

        for (int cel = col + 4; cel >= col; cel--) {
            try {
                //TODO 验证算法，目前只只实现一行
                if (chessBoard[row][cel] == pressId &&
                        chessBoard[row][cel - 1] == pressId &&
                        chessBoard[row][cel - 2] == pressId &&
                        chessBoard[row][cel - 3] == pressId &&
                        chessBoard[row][cel - 4] == pressId
                ) {
                    return pressId;
                }
            } catch (ArrayIndexOutOfBoundsException e) {
                System.out.println("正常错误");
            }
        }
        for (int rew = row - 4; rew <= row; rew++) {
            try {
                //TODO 验证算法，目前只只实现一行
                if (chessBoard[rew][col] == pressId &&
                        chessBoard[rew + 1][col] == pressId &&
                        chessBoard[rew + 2][col] == pressId &&
                        chessBoard[rew + 3][col] == pressId &&
                        chessBoard[rew + 4][col] == pressId
                ) {
                    return pressId;
                }
            } catch (ArrayIndexOutOfBoundsException e) {
                System.out.println("正常错误");
                return 0;
            }
        }

        for (int rew = row + 4; rew >= row; rew--) {
            try {
                //TODO 验证算法，目前只只实现一行
                if (chessBoard[rew][col] == pressId &&
                        chessBoard[rew - 1][col] == pressId &&
                        chessBoard[rew - 2][col] == pressId &&
                        chessBoard[rew - 3][col] == pressId &&
                        chessBoard[rew - 4][col] == pressId
                ) {
                    return pressId;
                }
            } catch (ArrayIndexOutOfBoundsException e) {
                System.out.println("正常错误");
            }
        }
        // *
        //  * 左斜上方
        for (int rew = row - 4, cel = col - 4; rew <= row && cel <= col; rew++, cel++) {
            try {
                //TODO 验证算法，目前只只实现一行
                if (chessBoard[row][cel] == pressId &&
                        chessBoard[row + 1][cel + 1] == pressId &&
                        chessBoard[row + 2][cel + 2] == pressId &&
                        chessBoard[row + 3][cel + 3] == pressId &&
                        chessBoard[row + 4][cel + 4] == pressId
                ) {
                    return pressId;
                }
            } catch (ArrayIndexOutOfBoundsException e) {
                System.out.println("正常错误");
            }

        }
       // *  右斜下方
       //  *
        for (int rew = row + 4, cel = col + 4; rew >= row && cel >= col; rew--, cel--) {
            try {
                //TODO 验证算法，目前只只实现一行
                if (chessBoard[row][cel] == pressId &&
                        chessBoard[row - 1][cel - 1] == pressId &&
                        chessBoard[row - 2][cel - 2] == pressId &&
                        chessBoard[row - 3][cel - 3] == pressId &&
                        chessBoard[row - 4][cel - 4] == pressId
                ) {
                    return pressId;
                }
            } catch (ArrayIndexOutOfBoundsException e) {
                System.out.println("正常错误");
            }
        }
        //  * 右斜上方
        // *
        for (int rew = row - 4, cel = col + 4; rew <= row && cel >= col; rew++, cel--) {
            try {
                //TODO 验证算法，目前只只实现一行
                if (chessBoard[row][cel] == pressId &&
                        chessBoard[row + 1][cel - 1] == pressId &&
                        chessBoard[row + 2][cel - 2] == pressId &&
                        chessBoard[row + 3][cel - 3] == pressId &&
                        chessBoard[row + 4][cel - 4] == pressId
                ) {
                    return pressId;
                }
            } catch (ArrayIndexOutOfBoundsException e) {
                System.out.println("正常错误");
            }
        }
        //   * 左斜下方
        //  *
        for (int rew = row + 4, cel = col - 4; rew >= row && cel <= col; rew--, cel++) {
            try {
                //TODO 验证算法，目前只只实现一行
                if (chessBoard[row][cel] == pressId &&
                        chessBoard[row - 1][cel + 1] == pressId &&
                        chessBoard[row - 2][cel + 2] == pressId &&
                        chessBoard[row - 3][cel + 3] == pressId &&
                        chessBoard[row - 4][cel + 4] == pressId
                ) {
                    return pressId;
                }
            } catch (ArrayIndexOutOfBoundsException e) {
                System.out.println("正常错误");
            }
        }
        return 0;


    }


    public void printChess() {
        System.out.println("当前棋盘日志-----------");
        for (int i = 0; i < MAX_ROW; i++) {
            for (int j = 0; j < MAX_COL; j++) {
                System.out.print(chessBoard[i][j] + " ");
            }
            System.out.println();
        }

    }


    public User getUser1() {
        return user1;
    }

    public void setUser1(User user1) {
        this.user1 = user1;
    }

    public User getUser2() {
        return user2;
    }

    public void setUser2(User user2) {
        this.user2 = user2;
    }

    public String getRoomId() {
        return roomId;
    }

    public void setRoomId(String roomId) {
        this.roomId = roomId;
    }

    public Integer getWhiteUser() {
        return whiteUser;
    }

    public void setWhiteUser(Integer whiteUser) {
        this.whiteUser = whiteUser;
    }
}
